home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / doslynx / src / htfwrite.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  13.3 KB  |  523 lines

  1. /*        FILE WRITER                HTFWrite.h
  2. **        ===========
  3. **
  4. **    This version of the stream object just writes to a C file.
  5. **    The file is assumed open and left open.
  6. **
  7. **    Bugs:
  8. **        strings written must be less than buffer size.
  9. */
  10. #define Uses_TFileDialog
  11. #define Uses_TProgram
  12. #define Uses_TDeskTop
  13. #define Uses_TObject
  14. #include"globals.h"
  15.  
  16. //    C callable
  17. extern "C"    {
  18.  
  19. #include"capalloc.h"
  20. #include"capstdio.h"
  21. #include "HTFWriter.h"
  22.  
  23. #include "HTFormat.h"
  24. #include "HTAlert.h"
  25. #include "HTFile.h"
  26. #include<dir.h>
  27.  
  28. /*        Stream Object
  29. **        ------------
  30. */
  31.  
  32. struct _HTStream {
  33.     CONST HTStreamClass *    isa;
  34.     
  35.     FILE *            fp;
  36.     char *             end_command;
  37.     char *             remove_command;
  38.     BOOL            announce;
  39. };
  40.  
  41.  
  42. /*_________________________________________________________________________
  43. **
  44. **        B L A C K    H O L E    C L A S S
  45. **
  46. **    There is only one black hole instance shared by anyone
  47. **    who wanst a black hole.  These black holes don't radiate,
  48. **    they just absorb data.
  49. */
  50. PRIVATE void HTBlackHole_put_character ARGS2(HTStream *, me, char, c)
  51. {}
  52. PRIVATE void HTBlackHole_put_string ARGS2(HTStream *, me, CONST char*, s)
  53. {}
  54. PRIVATE void HTBlackHole_write ARGS3(HTStream *, me, CONST char*, s, int, l)
  55. {}
  56. PRIVATE void HTBlackHole_free ARGS1(HTStream *, me)
  57. {}
  58. PRIVATE void HTBlackHole_abort ARGS2(HTStream *, me, HTError, e)
  59. {}
  60.  
  61.  
  62. /*    Black Hole stream
  63. **    -----------------
  64. */
  65. PRIVATE CONST HTStreamClass HTBlackHoleClass =
  66. {        
  67.     "BlackHole",
  68.     HTBlackHole_free,
  69.     HTBlackHole_abort,
  70.     HTBlackHole_put_character,     HTBlackHole_put_string,
  71.     HTBlackHole_write
  72. }; 
  73.  
  74. PRIVATE HTStream HTBlackHoleInstance =
  75. {
  76.     &HTBlackHoleClass,
  77.     NULL,
  78.     NULL,
  79.     NULL,
  80.     NO
  81. };
  82.  
  83. /*    Black hole craetion
  84. */
  85. PUBLIC HTStream * HTBlackHole NOARGS
  86. {
  87.     return &HTBlackHoleInstance;
  88. }
  89.  
  90.  
  91. /*_________________________________________________________________________
  92. **
  93. **        F I L E     A C T I O N     R O U T I N E S
  94. **  Bug:
  95. **    All errors are ignored.
  96. */
  97.  
  98. /*    Character handling
  99. **    ------------------
  100. */
  101.  
  102. PRIVATE void HTFWriter_put_character ARGS2(HTStream *, me, char, c)
  103. {
  104.     putc(c, me->fp);
  105. }
  106.  
  107.  
  108.  
  109. /*    String handling
  110. **    ---------------
  111. **
  112. **    Strings must be smaller than this buffer size.
  113. */
  114. PRIVATE void HTFWriter_put_string ARGS2(HTStream *, me, CONST char*, s)
  115. {
  116.     fputs(s, me->fp);
  117. }
  118.  
  119.  
  120. /*    Buffer write.  Buffers can (and should!) be big.
  121. **    ------------
  122. */
  123. PRIVATE void HTFWriter_write ARGS3(HTStream *, me, CONST char*, s, int, l)
  124. {
  125.     fwrite(s, 1, l, me->fp); 
  126. }
  127.  
  128.  
  129.  
  130.  
  131. /*    Free an HTML object
  132. **    -------------------
  133. **
  134. **    Note that the SGML parsing context is freed, but the created
  135. **    object is not,
  136. **    as it takes on an existence of its own unless explicitly freed.
  137. */
  138. PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
  139. {
  140.     fclose(me->fp);
  141.     if (me->end_command) {        /* Temp file */
  142.         HTProgress(me->end_command);    /* Tell user what's happening */
  143.     system(me->end_command);
  144.     free (me->end_command);
  145.     if (me->remove_command) {
  146.         system(me->remove_command);
  147.         free(me->remove_command);
  148.     }
  149.     }
  150.  
  151.     free(me);
  152. }
  153.  
  154. /*    End writing
  155. */
  156.  
  157. PRIVATE void HTFWriter_abort ARGS2(HTStream *, me, HTError, e)
  158. {
  159.     fclose(me->fp);
  160.     if (me->end_command) {        /* Temp file */
  161. #ifndef RELEASE
  162.     if (TRACE) fprintf(stderr,
  163.         "HTFWriter: Aborting: file not executed.\n");
  164. #endif /* RELEASE */
  165.     free (me->end_command);
  166.     if (me->remove_command) {
  167.         system(me->remove_command);
  168.         free(me->remove_command);
  169.     }
  170.     }
  171.  
  172.     free(me);
  173. }
  174.  
  175.  
  176.  
  177. /*    Structured Object Class
  178. **    -----------------------
  179. */
  180. PRIVATE CONST HTStreamClass HTFWriter = /* As opposed to print etc */
  181. {        
  182.     "FileWriter",
  183.     HTFWriter_free,
  184.     HTFWriter_abort,
  185.     HTFWriter_put_character,     HTFWriter_put_string,
  186.     HTFWriter_write
  187. }; 
  188.  
  189.  
  190. /*    Subclass-specific Methods
  191. **    -------------------------
  192. */
  193.  
  194. PUBLIC HTStream* HTFWriter_new ARGS1(FILE *, fp)
  195. {
  196.     HTStream* me;
  197.     
  198.     if (!fp) return NULL;
  199.  
  200.     me = (HTStream*)malloc(sizeof(*me));
  201.     if (me == NULL) outofmem(__FILE__, "HTML_new");
  202.     me->isa = &HTFWriter;       
  203.  
  204.     me->fp = fp;
  205.     me->end_command = NULL;
  206.     me->remove_command = NULL;
  207.     me->announce = NO;
  208.  
  209.     return me;
  210. }
  211.  
  212. /*    Make system command from template
  213. **    ---------------------------------
  214. **
  215. **    See mailcap spec for description of template.
  216. */
  217. /* @@ to be written.  sprintfs will do for now.  */
  218.  
  219.  
  220.  
  221. extern HTStream *HTSaveLocally(HTPresentation *HTPp_pres,
  222.     HTParentAnchor *HTPAp_anchor, HTStream *HTSp_sink)    {
  223. //    Purpose:    Prompt user for a local name to save under and return
  224. //            an open stream for WWW to write to that file.
  225. //    Arguments:    HTPp_pres    The routines used to present the
  226. //                    file to save.
  227. //            HTPAp_anchor    Not used, but is the anchor pointing
  228. //                    to this document.
  229. //            HTSp_sink    Not used, but is the stream to write
  230. //                    the presentation to.
  231. //    Return Value:    HTStream *    The opened stream for WWW to save the
  232. //                    file to.
  233. //                    It appears NULL can be returned in
  234. //                    the case of an error, but in such
  235. //                    cases we are just returning a null
  236. //                    stream so that the rest of the
  237. //                    code may continue to work.
  238. //    Remarks/Portability/Dependencies/Restrictions:
  239. //        On top of performing the normal functionality stated above,
  240. //        HTSaveLocally will have to inform the current TURLView that
  241. //        it should not try to display the URL that we are actually
  242. //        saving.
  243. //    Revision History:
  244. //        03-30-94    created
  245.  
  246.     //    First, inform the owning view that this we won't be able to
  247.     //    display this.
  248.     TURLV_current->DoNotDisplay();
  249.  
  250.     //    Secondly, check to make sure we can save locally.
  251.     //    This is taken directly from the WWW code and may not be
  252.     //    needed.
  253.     if(HTClientHost)    {
  254.         HTAlert("Can't save data to file -- please run WWW locally");
  255.         //    Return a stream that goes nowhere.
  256.         return(HTBlackHole());
  257.     }
  258.  
  259.  
  260.     //    Allocate the stream we will be returning.
  261.     auto HTStream *HTSp_me = new HTStream;
  262.     if(HTSp_me == NULL)    {
  263.         doslynxmessage("Could not allocate memory to save locally.");
  264.         //    Attempt to keep running by returning a black hole.
  265.         return(HTBlackHole());
  266.     }
  267.     //    Fill up a few members right now.
  268.     //    Use action routines of the HTFWriter.
  269.     //    No command to execute at the end.
  270.     //    No remove command to delete the file, will keep.
  271.     //    Announce??
  272.     HTSp_me->isa = &HTFWriter;
  273.     HTSp_me->end_command = NULL;
  274.     HTSp_me->remove_command = NULL;
  275.     HTSp_me->announce = YES;
  276.  
  277.     //    Create a file dialog to ask the user for a file name in which
  278.     //    to save in.
  279.     auto TFileDialog *TFD = new TFileDialog("*.*", HTPAp_anchor->address,
  280.             "Save as", fdOKButton, usi_SaveHist);
  281.  
  282.     //    If the dialog was not allocated
  283.     if(TFD == NULL)    {
  284.         doslynxmessage("Could not allocate memory to save locally.");
  285.         //    Keep running by returning the black hole.
  286.         return(HTBlackHole());
  287.     }
  288.  
  289.     //    Execute the dialog.
  290.     auto unsigned short int usi_retval = TProgram::deskTop->execView(TFD);
  291.  
  292.     //    If the user didn't cancel.
  293.     if(usi_retval == cmCancel)    {
  294.         TObject::destroy(TFD);
  295.         //    Return the black hole to save in, user doesn't want
  296.         //    it.
  297.         return(HTBlackHole());
  298.     }
  299.  
  300.     //    Small buffer to hold file name
  301.     auto char ca_buffer[usi_TILURLSize];
  302.  
  303.     //    Get the information from the Dialog
  304.     TFD->getFileName(ca_buffer);
  305.  
  306.     //    Done with the dialog.
  307.     TObject::destroy(TFD);
  308.  
  309.     //    Open the stream's file.
  310.     HTSp_me->fp = fopen(ca_buffer, "wb");
  311.     if(HTSp_me->fp == NULL)    {
  312.         doslynxmessage("Unable to open local file " << ca_buffer
  313.             << " for writing.");
  314.         //    Return the black hole.
  315.         return(HTBlackHole());
  316.     }
  317.  
  318.     //    Done, return the allocated stream.
  319.     return(HTSp_me);
  320. }
  321.  
  322.  
  323. extern HTStream *HTHandleImage(HTPresentation *HTPp_pres,
  324.     HTParentAnchor *HTPAp_anchor, HTStream *HTSp_sink)    {
  325. //    Purpose:    Prompt user for a local name to save under and return
  326. //            an open stream for WWW to write to that file.  Also,
  327. //            inform the owning view that this is a viewable image.
  328. //    Arguments:    HTPp_pres    The routines used to present the
  329. //                    file to save.
  330. //            HTPAp_anchor    Not used, but is the anchor pointing
  331. //                    to this document.
  332. //            HTSp_sink    Not used, but is the stream to write
  333. //                    the presentation to.
  334. //    Return Value:    HTStream *    The opened stream for WWW to save the
  335. //                    file to.
  336. //                    It appears NULL can be returned in
  337. //                    the case of an error, but in such
  338. //                    cases we are just returning a null
  339. //                    stream so that the rest of the
  340. //                    code may continue to work.
  341. //    Remarks/Portability/Dependencies/Restrictions:
  342. //        On top of performing the normal functionality stated above,
  343. //        HTHandleImage will have to inform the current TURLView that
  344. //        it should not try to display the URL that we are actually
  345. //        saving.  Also, we will inform the owning view that this is
  346. //        a viewable image, so that once the load is accomplished, to
  347. //        display.
  348. //    Revision History:
  349. //        03-30-94    created
  350. //        04-06-94    Converted for images.
  351.  
  352.     //    First, inform the owning view that this we won't be able to
  353.     //    display this.
  354.     TURLV_current->DoNotDisplay();
  355.  
  356.     //    Secondly, check to make sure we can save locally.
  357.     //    This is taken directly from the WWW code and may not be
  358.     //    needed.
  359.     if(HTClientHost)    {
  360.         HTAlert("Can't save data to file -- please run WWW locally");
  361.         //    Return a stream that goes nowhere.
  362.         return(HTBlackHole());
  363.     }
  364.  
  365.  
  366.     //    Allocate the stream we will be returning.
  367.     auto HTStream *HTSp_me = new HTStream;
  368.     if(HTSp_me == NULL)    {
  369.         doslynxmessage("Could not allocate memory to save locally.");
  370.         //    Attempt to keep running by returning a black hole.
  371.         return(HTBlackHole());
  372.     }
  373.     //    Fill up a few members right now.
  374.     //    Use action routines of the HTFWriter.
  375.     //    No command to execute at the end.
  376.     //    No remove command to delete the file, will keep.
  377.     //    Announce??
  378.     HTSp_me->isa = &HTFWriter;
  379.     HTSp_me->end_command = NULL;
  380.     HTSp_me->remove_command = NULL;
  381.     HTSp_me->announce = YES;
  382.  
  383.     //    Create a file dialog to ask the user for a file name in which
  384.     //    to save in.
  385.     auto TFileDialog *TFD = new TFileDialog("*.gif", HTPAp_anchor->
  386.         address, "Save image as", fdOKButton, usi_SaveHist);
  387.  
  388.     //    If the dialog was not allocated
  389.     if(TFD == NULL)    {
  390.         doslynxmessage("Could not allocate memory to save locally.");
  391.         //    Keep running by returning the black hole.
  392.         return(HTBlackHole());
  393.     }
  394.  
  395.     //    Execute the dialog.
  396.     auto unsigned short int usi_retval = TProgram::deskTop->execView(TFD);
  397.  
  398.     //    If the user didn't cancel.
  399.     if(usi_retval == cmCancel)    {
  400.         TObject::destroy(TFD);
  401.         //    Return the black hole to save in, user doesn't want
  402.         //    it.
  403.         return(HTBlackHole());
  404.     }
  405.  
  406.     //    Small buffer to hold file name
  407.     auto char ca_buffer[usi_TILURLSize];
  408.  
  409.     //    Get the information from the Dialog
  410.     TFD->getFileName(ca_buffer);
  411.  
  412.     //    Done with the dialog.
  413.     TObject::destroy(TFD);
  414.  
  415.     //    Open the stream's file.
  416.     HTSp_me->fp = fopen(ca_buffer, "wb");
  417.     if(HTSp_me->fp == NULL)    {
  418.         doslynxmessage("Unable to open local file " << ca_buffer
  419.             << " for writing.");
  420.         //    Return the black hole.
  421.         return(HTBlackHole());
  422.     }
  423.  
  424.     //    Here we can inform the owning window that this is an image.
  425.     //    Pass the file name so that the view can take action upon it.
  426.     TURLV_current->isImage(ca_buffer);
  427.  
  428.     //    Done, return the allocated stream.
  429.     return(HTSp_me);
  430. }
  431.  
  432.  
  433.  
  434.  
  435. /*    Take action using a system command
  436. **    ----------------------------------
  437. **
  438. **    originally from Ghostview handling by Marc Andreseen.
  439. **    Creates temporary file, writes to it, executes system command
  440. **    on end-document.  The suffix of the temp file can be given
  441. **    in case the application is fussy, or so that a generic opener can
  442. **    be used.
  443. */
  444. PUBLIC HTStream* HTSaveAndExecute ARGS3(
  445.     HTPresentation *,    pres,
  446.     HTParentAnchor *,    anchor,    /* Not used */
  447.     HTStream *,        sink)    /* Not used */
  448.  
  449. #ifdef unix
  450. #define REMOVE_COMMAND "/bin/rm -f %s\n"
  451. #endif
  452. #ifdef VMS
  453. #define REMOVE_COMMAND "delete/noconfirm/nolog %s.."
  454. #endif
  455.  
  456. #ifdef REMOVE_COMMAND
  457. {
  458.     char *fnam;
  459.     CONST char * suffix;
  460.     
  461.     HTStream* me;
  462.     
  463.     if (HTClientHost) {
  464.         HTAlert("Can't save data to file -- please run WWW locally");
  465.     return HTBlackHole();
  466.     }
  467.  
  468.     me = (HTStream*)malloc(sizeof(*me));
  469.     if (me == NULL) outofmem(__FILE__, "Save and execute");
  470.     me->isa = &HTFWriter;  
  471.     
  472.     /* Save the file under a suitably suffixed name */
  473.     
  474.     suffix = HTFileSuffix(pres->rep);
  475.  
  476.     fnam = (char *)malloc (L_tmpnam + 16 + strlen(suffix));
  477.     tmpnam (fnam);
  478.     if (suffix) strcat(fnam, suffix);
  479.     
  480.     me->fp = fopen (fnam, "w");
  481.     if (!me->fp) {
  482.     HTAlert("Can't open temporary file!");
  483.         free(fnam);
  484.     free(me);
  485.     return NULL;
  486.     }
  487.  
  488. /*    Make command to process file
  489. */
  490.     me->end_command = (char *)malloc (
  491.                 (strlen (pres->command) + 10+ 3*strlen(fnam))
  492.                  * sizeof (char));
  493.     if (me == NULL) outofmem(__FILE__, "SaveAndExecute");
  494.     
  495.     sprintf (me->end_command, pres->command, fnam, fnam, fnam);
  496.  
  497.     me->remove_command = NULL;    /* If needed, put into end_command */
  498. #ifdef NOPE
  499. /*    Make command to delete file
  500. */ 
  501.     me->remove_command = (char *)malloc (
  502.                 (strlen (REMOVE_COMMAND) + 10+ strlen(fnam))
  503.                  * sizeof (char));
  504.     if (me == NULL) outofmem(__FILE__, "SaveAndExecute");
  505.     
  506.     sprintf (me->remove_command, REMOVE_COMMAND, fnam);
  507. #endif
  508.  
  509.     me->announce = NO;
  510.     free (fnam);
  511.     return me;
  512. }
  513.  
  514. #else    /* can do remove */
  515. { return NULL; }
  516. #endif
  517.  
  518.  
  519. /*    Format Converter using system command
  520. **    -------------------------------------
  521. */
  522.  
  523. }; // extern "C"